﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.IO;
using Microsoft.Practices.Unity.Configuration;

namespace Tjb.Config
{
    public partial class Form1 : Form
    {
        public string opentFilter = "程序集|*.dll|所有文件|*.*";
        private OpenFileDialog openFileDialogIntf;
        private OpenFileDialog openFileDialogImpl;
        public Form1()
        {
            InitializeComponent();
            this.openFileDialogIntf = new OpenFileDialog();
            this.openFileDialogIntf.InitialDirectory = Environment.CurrentDirectory;
            this.openFileDialogIntf.Filter = this.opentFilter;
            openFileDialogIntf.Multiselect = true;

            this.openFileDialogImpl = new OpenFileDialog();
            this.openFileDialogImpl.InitialDirectory = Environment.CurrentDirectory;
            this.openFileDialogImpl.Filter = this.opentFilter;
            this.openFileDialogImpl.Multiselect = true;
        }

        private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            this.treeView1.Nodes.Clear();
            string[] files = this.openFileDialogIntf.FileNames;

            BuildIntf(files);
        }

        //  private List<string> intfFiles = new List<string>();

        public void BuildIntf(string[] files)
        {
            foreach (string f in files)
            {
                TreeNode node = new TreeNode();
                node.Text = Path.GetFileName(f);
                Assembly ass = Assembly.LoadFrom(f);

                Build(ass.GetTypes(), ref node, delegate(Type curretType)
                {
                    if (curretType.IsGenericType || curretType.IsNotPublic)
                        return false;
                    if (curretType.IsAbstract || curretType.IsInterface)
                        return true;
                    return false;
                });
                this.treeView1.Nodes.Add(node);
            }
        }
        class mapping
        {
            public mapping(Type basetype)
            {
                this.basetype = basetype;
            }
            public Type basetype;
            public List<Type> extendtype = new List<Type>();
        }
        public delegate bool Filter(Type curretType);
        public delegate bool BuildExtend(string files, ref TreeNode baseNode);
        public void Build(Type[] types, ref TreeNode parent, Filter filter)
        {
            foreach (Type t in types)
            {
                if (filter(t))
                {
                    TreeNode lastNameSpace = GetLastNode(t.Namespace, ref parent);
                    TreeNode typeNode = new TreeNode();
                    typeNode.Name = t.Name;
                    typeNode.Text = t.Name;
                    typeNode.Tag = new mapping(t);
                    buildextend(ref typeNode);
                    lastNameSpace.Nodes.Add(typeNode);
                }
            }
        }
        public void buildextend(ref TreeNode baseNode)
        {
            mapping map = baseNode.Tag as mapping;
            if (map != null)
            {
                map.extendtype.Clear();
                baseNode.Nodes.Clear();
                var files = listBox1.Items.Cast<string>();

                if (files != null)
                {
                    IEnumerator<String> ifile = files.GetEnumerator();
                    while (ifile.MoveNext())
                    {
                        mybuildextend(ifile.Current, ref baseNode);
                    }
                }
            }
        }

        BuildExtend mybuildextend = delegate(string file, ref TreeNode baseNode)
        {
            mapping map = baseNode.Tag as mapping;
            if (map != null)
            {
                Assembly ass = Assembly.LoadFrom(file);
                Type[] types = ass.GetTypes();
                foreach (Type ext in types)
                {
                    if (map.basetype != ext && map.basetype.IsAssignableFrom(ext))
                    {
                        TreeNode node = new TreeNode();
                        node.Tag = ext;
                        node.Text = "[]" + ext.FullName;
                        node.ForeColor = Color.Red;

                        baseNode.Nodes.Add(node);
                        if (!baseNode.IsExpanded)
                            baseNode.ExpandAll();
                        if (baseNode.Nodes.Count == 1)
                        {
                            map.extendtype.Add(ext);
                            node.Checked = true;
                        }
                    }

                }
            }
            return true;
        };
        private TreeNode GetLastNode(string fullNameSpace, ref TreeNode parent)
        {
            TreeNode cur = parent;
            if (fullNameSpace != null)
            {
                cur = cur = GetAndBuildChildNodeByKEY(fullNameSpace, ref cur);
                //string[] names = fullNameSpace.Split('.');
                //foreach (string name in names)
                //{
                //    cur = GetAndBuildChildNodeByKEY(name, ref cur);
                //}
            }
            return cur;
        }
        private TreeNode GetAndBuildChildNodeByKEY(string keyName, ref TreeNode parent)
        {
            TreeNode cur = parent.FirstNode;
            while (cur != null)
            {
                if (cur.Name == keyName)
                {
                    return cur;
                }
                cur = cur.NextNode;
            }
            cur = new TreeNode();
            cur.Name = keyName;
            cur.Text = keyName;
            parent.Nodes.Add(cur);
            return cur;

        }


        private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
        {
            TreeNode node = e.Node;
            SetNodeCheckState(node, node.Checked);
        }
        void SetNodeCheckState(TreeNode parent, bool state)
        {
            Type i = parent.Tag as Type;
            mapping map = parent.Parent == null ? null : parent.Parent.Tag as mapping;
            if (map != null && i != null)
            {
                if (state)
                    map.extendtype.Add(i);
                else
                    map.extendtype.Remove(i);
            }
            TreeNode node = parent.FirstNode;
            while (node != null)
            {
                node.Checked = state;
                SetNodeCheckState(node, state);
                node = node.NextNode;
            }
        }


        private void treeloadfile_Click(object sender, EventArgs e)
        {
            DialogResult result = this.openFileDialogIntf.ShowDialog();
            if (result == DialogResult.OK)
            {
                openFileDialog1_FileOk(null, null);
            }
        }
        private List<string> implFiles = new List<string>();
        private void loadfile_Click(object sender, EventArgs e)
        {
            DialogResult result = this.openFileDialogImpl.ShowDialog();
            if (result == DialogResult.OK)
            {
                this.listBox1.Items.AddRange(this.openFileDialogImpl.FileNames);
            }
        }

        private void 删除选中ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ListBox.SelectedObjectCollection objes = this.listBox1.SelectedItems;
            for (int i = 0, n = objes.Count; i < n; i++)
            {
                this.listBox1.Items.Remove(objes[i]);
            }
        }

        private void 删除选中ToolStripMenuItem1_Click(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            configuration cfg = configuration.Instance;
            unity u = cfg.unity = new unity();
            u.containers = new List<container>();
            u.typeAliases = new List<typeAlias>();
            u.typeAliases.Add(new typeAlias());
            container c = new container();
            c.name = "containerName";
            c.types = new List<type>();
            foreach (TreeNode node in this.treeView1.Nodes)
            {
                save(node, ref  c.types);
            }
            u.containers.Add(c);
            cfg.Save();
        }
        void save(TreeNode node, ref List<type> types)
        {
            TreeNode baseNode = node.FirstNode;

            while (baseNode != null)
            {
                mapping map = baseNode.Tag as mapping;
                if (map != null)
                {
                    foreach (Type ext in map.extendtype)
                    {
                        type tp = new type();
                        tp.mtype = map.basetype.FullName + "," + map.basetype.Assembly.FullName;
                        tp.mapTo = ext.FullName + "," + ext.Assembly.FullName;
                        tp.lifetime = new lifetime();
                        types.Add(tp);
                    }

                }

                save(baseNode, ref types);
                baseNode = baseNode.NextNode;
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //TODO asdf
            foreach (TreeNode node in this.treeView1.Nodes)
            {
                research(node);
            }
        }
        void research(TreeNode parent)
        {
            TreeNode baseNode = parent.FirstNode;

            while (baseNode != null)
            {
                mapping map = baseNode.Tag as mapping;
                if (map != null)
                {
                    buildextend(ref baseNode);
                }

                research(baseNode);
                baseNode = baseNode.NextNode;
            }
        }

        private void 删除类型ToolStripMenuItem_Click(object sender, EventArgs e)
        {



        }

        private void 删除扩展ToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }
    }

}
